#include "sk_box_shape_item.h"
#include "sk_game_item_property.h"
#include "sk_game_level.h"
#include "sk_level_item.h"
#include "sk_game_item_proxy.h"
#include "sk_box_shape.h"
#include "sk_b2_properties_helper.h"

#include <QPainter>

#include <QPainter>
#include <QGraphicsPolygonItem>
#include <QPolygonF>
#include <QDebug>
#include <QEvent>

#include "userdata.h"
#include "projectexplorer.h"

namespace sk
{
    class BoxShapeGraphicsItem : public QGraphicsPolygonItem
    {
    public:
        BoxShapeGraphicsItem(BoxShapeItem * item)
            :
        QGraphicsPolygonItem()
        {
            setFlag(QGraphicsItem::ItemIsMovable);
            setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
            _item = item;
            rebuildShape();
        }
        int type () const
        {
            return 66666;
        }

        void rebuildShape()
        {
            BoxShape * s = _item->shape();
            QPolygonF p;
            p << QPointF(0, 0) << QPointF(s->w, 0) << QPointF(s->w, s->h) << QPointF(0, s->h);
            setPolygon(p);
        }

    protected:
        void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 )
        {
            QGraphicsPolygonItem::paint(painter, option, widget);
            if (pen().color() == Qt::darkYellow)
            {
                QRectF r = boundingRect();
                painter->drawText(r, QString::number(_item->index()), Qt::AlignHCenter | Qt::AlignVCenter);
            }
        }

        bool sceneEvent(QEvent * event)
        {
            if (event->type() == QEvent::GraphicsSceneMousePress)
            {
                _UD.pe->activate(_item);
            }
            return QGraphicsPolygonItem::sceneEvent(event);
        }
        QVariant itemChange(GraphicsItemChange change, const QVariant &value)
        {
            if (change == ItemScenePositionHasChanged && scene())
            {
                QPointF newPos = value.toPointF();
                BoxShape * s = _item->shape();
                s->bodyDef.position.x = newPos.x();
                s->bodyDef.position.y = newPos.y();
                _UD.pe->updateProperty("position.x");
                _UD.pe->updateProperty("position.y");
            }
            return QGraphicsItem::itemChange(change, value);
        }
    private:
        BoxShapeItem * _item;
    };


    BoxShapeItem::BoxShapeItem(GameItem * parent, int ind /*= 0*/)
        :
        GameItem(parent, ind)
    {
    }

    void BoxShapeItem::onPropertyChange(GameItemProperty * property)
    {
        if (_sceneItem)
        {
            BoxShapeGraphicsItem * item = static_cast<BoxShapeGraphicsItem *>(_sceneItem);
            if (property->name == "position.x" || property->name == "position.y" || property->name == "angle")
            {
                GameItemFloatProperty * p = static_cast<GameItemFloatProperty *>(property);
                if (property->name == "position.x")
                {
                    float x = *(p->data);
                    //qDebug() << "x" << x;
                    item->setPos(x, item->scenePos().y());
                }
                else
                if (property->name == "position.y")
                {
                    float y = *(p->data);
                    //qDebug () << "y" << y;
                    item->setPos(item->scenePos().x(), y);
                }
                else
                if (property->name == "angle")
                {
                    float angle = *(p->data);
                    item->setRotation(angle);
                }
            }
            else
            if (property->name == "width" || property->name == "height")
            {
                item->rebuildShape();
            }
        }
    }


    QGraphicsItem * BoxShapeItem::createSceneItem()
    {
        BoxShape * c = shape();
        _sceneItem = new BoxShapeGraphicsItem(this);
        Q_ASSERT(parent()->child(index())->_sceneItem == _sceneItem);
        _sceneItem->setPos(c->bodyDef.position.x, c->bodyDef.position.y);
        _sceneItem->setRotation(c->bodyDef.angle);
        return _sceneItem;
    }

    GameItemType BoxShapeItem::type()
    {
        return IT_BoxShape;
    }

    BoxShape * BoxShapeItem::shape()
    {
        // TODO : think how fit this easily
        GameItemProxy * p = static_cast<GameItemProxy *>(parent());
        LevelItem     * l = static_cast<LevelItem*>(p->parent());
        int i = index();
        return static_cast<BoxShape *>(p->index() == 0 ? l->level()->shapes[i].get() : l->level()->dropShapes[i].get());

    }

    int BoxShapeItem::numProperties()
    {
        return 2 + B2PropertiesHelper::numBodyDefProperties() + B2PropertiesHelper::numFixtureDefProperties();
    }

    GameItemProperty * BoxShapeItem::getProperty(int ind)
    {
        BoxShape * s = shape();
        if (0 == ind)
        {
            return new GameItemFloatProperty(this, "width", &(s->w));
        }
        if (1 == ind)
        {
            return new GameItemFloatProperty(this, "height", &(s->h));
        }
        ind -= 2;

        if (ind < B2PropertiesHelper::numFixtureDefProperties())
        {
            return B2PropertiesHelper::fixtureDefProperty(this, ind, &s->fixtureDef);
        }
        else
        {
            ind -= B2PropertiesHelper::numFixtureDefProperties();
        }
        return B2PropertiesHelper::bodyDefProperty(this, ind, &s->bodyDef);
    }


    void BoxShapeItem::paint(QPainter * painter, const QStyleOptionViewItem & option, int row, int column)
    {
        painter->save();

        fillBg(painter, option, row, column);

        if (column == 0)
        {

            if ( (option.state & QStyle::State_MouseOver) || (option.state & QStyle::State_Selected) )
            {
                painter->setPen(Qt::white);
            }
            else
            {
                painter->setPen(Qt::black);
            }

            QRect rect(option.rect.left() + (int)(option.rect.height() * .2),
                       option.rect.top() + (int)(option.rect.height() * .2),
                       (int)(option.rect.height() * .6),
                       (int)(option.rect.height() * .6));
            painter->drawRect(rect);
            //painter->fillRect(rect, painter->pen().color());
        }

        painter->restore();
    }

    bool BoxShapeItem::canDeleteFromProjectExplorer()
    {
        return true;
    }

} // namespace sk



